import numpy as np
from datetime import datetime
from collections import defaultdict


class ClothingItem:
    def __init__(self, clothes_id,category, subcategory, color, material, season, fit, embedding=None):
        """
        初始化服装项

        参数:
            clothes_id: 衣服唯一标识符
            category: 大类 (上衣、裤子、裙子、鞋子、其他)
            subcategory: 子类 (如毛衣、衬衣等)
            color: 颜色 (如红色、黑色等)
            material: 材质 (如皮革、牛仔布、棉等)
            season: 适穿季节 (如夏季、春秋、秋冬、冬季等)
            fit: 版型 (如合适、宽松、紧身等)
            embedding: 衣服的特征向量表示 (可选)
        """
        self.clothes_id = clothes_id
        #self.image_url=image_url
        self.category = category
        self.subcategory = subcategory
        self.color = color
        self.material = material
        self.season = season
        self.fit = fit

        # 如果没有提供embedding，则根据属性生成一个简单的特征向量
        if embedding is None:
            self.embedding = self._generate_embedding()
        else:
            self.embedding = embedding

    def _generate_embedding(self, dim=50):
        """根据衣服属性生成简单的特征向量"""
        # 这里使用随机向量模拟，实际应用中应该使用更复杂的特征提取方法
        # 例如基于图像的特征提取或基于属性的嵌入
        np.random.seed(hash(str(self.clothes_id)) % 2 ** 32)
        return np.random.rand(dim)

    def __str__(self):
        return f"ID: {self.clothes_id},{self.category}-{self.subcategory}, {self.color}, {self.material}, {self.season}, {self.fit}"


class Outfit:
    def __init__(self, outfit_id, items, user_id=None):
        """
        初始化服装搭配

        参数:
            outfit_id: 搭配唯一标识符
            items: ClothingItem对象列表
            user_id: 用户ID (可选)
        """
        self.outfit_id = outfit_id
        self.items = items
        self.user_id = user_id

    def get_item_ids(self):
        """获取搭配中所有衣服的ID"""
        return [item.clothes_id for item in self.items]

    def get_outfit_embedding(self):
        """获取搭配的特征向量表示"""
        if not self.items:
            return np.zeros(50)  # 默认维度

        # 简单地平均所有衣服的特征向量
        item_embeddings = [item.embedding for item in self.items]
        return np.mean(item_embeddings, axis=0)

    def get_categories(self):
        """获取搭配中包含的所有大类"""
        return set(item.category for item in self.items)

    def get_season_compatibility(self):
        """计算搭配的季节兼容性"""
        seasons = [item.season for item in self.items]
        # 如果所有衣服都适合同一季节，则兼容性最高
        if len(set(seasons)) == 1:
            return 1.0

        # 增强的季节兼容性计算
        season_map = {
            "春季": [0],
            "夏季": [1],
            "秋季": [2],
            "冬季": [3],
            "春秋": [0, 2],
            "秋冬": [2, 3],
            "春夏": [0, 1],
            "四季": [0, 1, 2, 3]
        }

        compatible_count = 0
        total_pairs = 0

        for i in range(len(seasons)):
            for j in range(i + 1, len(seasons)):
                total_pairs += 1
                season_i = season_map.get(seasons[i], [])
                season_j = season_map.get(seasons[j], [])

                # 检查是否有重叠的季节
                overlap = set(season_i).intersection(set(season_j))
                if overlap:
                    # 根据重叠季节的数量计算兼容性分数
                    compatible_count += len(overlap) / max(len(season_i), len(season_j))
                else:
                    # 检查季节是否相邻
                    adjacent = False
                    for si in season_i:
                        for sj in season_j:
                            if abs(si - sj) == 1 or abs(si - sj) == 3:  # 相邻或冬春相邻
                                adjacent = True
                                break
                    if adjacent:
                        compatible_count += 0.5  # 相邻季节给予部分兼容性

        return compatible_count / total_pairs if total_pairs > 0 else 0.0

    def __str__(self):
        categories = {}
        for item in self.items:
            if item.category not in categories:
                categories[item.category] = []
            categories[item.category].append(f"{item.subcategory}({item.color})")

        outfit_str = f"搭配: {self.outfit_id}"
        if self.user_id:
            outfit_str += f" (用户: {self.user_id})"
        outfit_str += "\n"

        for category, items in categories.items():
            outfit_str += f"  {category}: {', '.join(items)}\n"

        return outfit_str


class UserProfile:
    def __init__(self, user_id):
        """
        初始化用户档案

        参数:
            user_id: 用户唯一标识符
        """
        self.user_id = user_id
        self.liked_outfits = []
        self.liked_items = []
        self.interaction_history = []

        # 用户对各属性的偏好
        self.preferences = {
            "category": defaultdict(float),
            "subcategory": defaultdict(float),
            "color": defaultdict(float),
            "material": defaultdict(float),
            "season": defaultdict(float),
            "fit": defaultdict(float)
        }

        # 用户对搭配风格的偏好
        self.style_preferences = defaultdict(float)

    def update_preferences(self, outfit, rating, style=None):
        """
        根据用户对搭配的评分更新偏好

        参数:
            outfit: 用户评价的搭配
            rating: 评分 (1-5)
            style: 搭配风格 (可选)
        """
        # 归一化评分到[-1, 1]区间
        normalized_rating = (rating - 3) / 2

        # 更新搭配历史
        self.interaction_history.append((outfit, rating))

        # 如果评分较高，添加到喜欢的搭配和衣服中
        if rating > 3:
            self.liked_outfits.append(outfit)
            self.liked_items.extend(outfit.items)

        # 更新对各属性的偏好
        # 添加上限
        MAX_PREFERENCE = 2.0  # 设置偏好上限
        for item in outfit.items:
            # 更新各属性偏好，但限制最大值
            for attr_type, attr_dict in self.preferences.items():
                attr_value = getattr(item, attr_type.lower(), None)
                if attr_value:
                    current = attr_dict.get(attr_value, 0)
                    attr_dict[attr_value] = min(MAX_PREFERENCE, current + normalized_rating)

        # 如果提供了风格信息，更新风格偏好
        if style:
            current = self.style_preferences.get(style, 0)
            self.style_preferences[style] = min(MAX_PREFERENCE, current + normalized_rating)

    def get_top_preferences(self, attribute, n=3):
        """获取用户对某属性的前n个偏好"""
        prefs = self.preferences[attribute]
        sorted_prefs = sorted(prefs.items(), key=lambda x: x[1], reverse=True)
        return [item for item in sorted_prefs[:n] if item[1] > 0]

    def get_preference_vector(self, all_attributes):
        """
        生成用户偏好向量

        参数:
            all_attributes: 包含所有可能属性值的字典
        """
        # 初始化偏好向量
        preference_vector = []

        # 为每个属性类别添加偏好值
        for attr_type, attr_values in all_attributes.items():
            for value in attr_values:
                preference_vector.append(self.preferences[attr_type].get(value, 0))

        return np.array(preference_vector)

    def __str__(self):
        output = f"用户: {self.user_id}\n"

        output += "颜色偏好: "
        color_prefs = self.get_top_preferences("color")
        if color_prefs:
            output += ", ".join([f"{color}({score:.2f})" for color, score in color_prefs])
        else:
            output += "无明显偏好"
        output += "\n"

        output += "季节偏好: "
        season_prefs = self.get_top_preferences("season")
        if season_prefs:
            output += ", ".join([f"{season}({score:.2f})" for season, score in season_prefs])
        else:
            output += "无明显偏好"
        output += "\n"

        output += "风格偏好: "
        style_prefs = sorted(self.style_preferences.items(), key=lambda x: x[1], reverse=True)
        if style_prefs and style_prefs[0][1] > 0:
            output += ", ".join([f"{style}({score:.2f})" for style, score in style_prefs[:3] if score > 0])
        else:
            output += "无明显偏好"

        return output


class ContextInfo:
    def __init__(self, date=None, weather=None, style_theme=None):
        """
        初始化上下文信息

        参数:
            date: 日期 (datetime对象或字符串)
            weather: 天气情况 (如晴天、雨天等)
            style_theme: 风格主题 (如休闲、正式、运动等)
        """
        if date is None:
            self.date = datetime.now()
        elif isinstance(date, str):
            try:
                self.date = datetime.strptime(date, "%Y-%m-%d")
            except ValueError:
                self.date = datetime.now()
        else:
            self.date = date

        self.weather = weather
        self.style_theme = style_theme
        self.manual_season = None  # 添加手动设置季节的属性
        self.scene = None  # 添加场景属性
        self.temperature = None  # 添加温度属性

    def get_season(self):
        """根据日期确定季节，如果手动设置了季节则优先使用"""
        # 如果手动设置了季节，优先使用
        if self.manual_season:
            return self.manual_season

        # 否则根据日期确定季节
        if not self.date:
            return "四季"  # 默认返回四季

        month = self.date.month
        if 3 <= month <= 5:
            return "春季"
        elif 6 <= month <= 8:
            return "夏季"
        elif 9 <= month <= 11:
            return "秋季"
        else:
            return "冬季"


    def get_temperature_range(self):
        """根据季节和天气估计温度范围"""
        season = self.get_season()

        # 基础温度范围
        temp_ranges = {
            "春季": (10, 20),
            "夏季": (25, 35),
            "秋季": (15, 25),
            "冬季": (-5, 10)
        }

        base_low, base_high = temp_ranges.get(season, (15, 25))

        # 根据天气调整
        if self.weather == "雨天":
            return (base_low - 2, base_high - 2)
        elif self.weather == "晴天":
            return (base_low + 2, base_high + 2)
        elif self.weather == "阴天":
            return (base_low - 1, base_high - 1)
        elif self.weather == "雪天":
            return (base_low - 5, base_high - 5)

        return (base_low, base_high)

    def __str__(self):
        season = self.get_season()
        temp_range = self.get_temperature_range()

        return (f"日期: {self.date.strftime('%Y-%m-%d')}, 季节: {season}, "
                f"天气: {self.weather or '未知'}, "
                f"温度范围: {temp_range[0]}°C-{temp_range[1]}°C, "
                f"风格主题: {self.style_theme or '未指定'}")
